﻿using EFXpoAdoCompare.Models;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace EFXpoAdoCompare.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }

        void EFSave(Person[] persons)
        {
            ApplicationDbContext db = new ApplicationDbContext();
            db.Persons.AddRange(persons);
            db.SaveChanges();
        }

        void AdoSave(Person[] persons)
        {
            SqlConnection conn = new ApplicationDbContext().Database.Connection as SqlConnection;
            conn.Open();
            using (SqlTransaction trans = conn.BeginTransaction())
            {
                SqlCommand cmd = new SqlCommand(@"INSERT INTO Person (Birthdate,RegTime,UserName,Mark)
VALUES(@Birthdate,@RegTime,@UserName,@Mark)", conn, trans);
                cmd.Parameters.Add("Birthdate", System.Data.SqlDbType.Date);
                cmd.Parameters.Add("RegTime", System.Data.SqlDbType.DateTime);
                cmd.Parameters.Add("UserName", System.Data.SqlDbType.NVarChar);
                cmd.Parameters.Add("Mark", System.Data.SqlDbType.NVarChar);

                foreach (var p in persons)
                {
                    cmd.Parameters["Birthdate"].Value = p.Birthdate;
                    cmd.Parameters["RegTime"].Value = p.RegTime;
                    cmd.Parameters["UserName"].Value = p.UserName;
                    cmd.Parameters["Mark"].Value = p.Mark;

                    cmd.ExecuteNonQuery();
                }
                trans.Commit();
            }
            conn.Close();
        }

        void EFSearch(Person[] persons)
        {
            ApplicationDbContext db = new ApplicationDbContext();
            var list = db.Persons.Where(p => p.UserName.CompareTo("d")>=1).Take(10000).ToList();
            ViewBag.List = list;
        }

        void AdoSearch(Person[] persons)
        {
            SqlConnection conn = new ApplicationDbContext().Database.Connection as SqlConnection;
            conn.Open();
            string sql = "SELECT TOP 10000 * FROM Person WHERE UserName >= 'd'";
            SqlCommand comm = new SqlCommand(sql, conn);
            List<Person> ps = new List<Person>();
            using (SqlDataReader reader = comm.ExecuteReader())
            {
                while (reader.Read())
                {
                    ps.Add(new Person()
                    {
                        Birthdate = (DateTime)reader["Birthdate"],
                        Id = (int)reader["Id"],
                        UserName = (string)reader["UserName"],
                        Mark = (string)reader["Mark"],
                        RegTime = (DateTime)reader["RegTime"],
                    });
                }
            }
            ViewBag.List = ps;
            conn.Close();
        }

        public ActionResult SearchPerson()
        {
            PersonsCreater pc = new PersonsCreater();

            pc.OnPersonsSaving = EFSearch;
            ViewBag.EFMS = pc.SavePersons();

            pc.OnPersonsSaving = AdoSearch;

            ViewBag.AdoMS = pc.SavePersons();
            return View();
        }

        public ActionResult CreatePerson()
        {
            PersonsCreater pc = new PersonsCreater();

            pc.OnPersonsSaving = EFSave;
            ViewBag.EFMS = pc.SavePersons();

            pc.OnPersonsSaving = AdoSave;

            ViewBag.AdoMS = pc.SavePersons();
            return View();
        }
    }

    class PersonsCreater
    {
        public Action<Person[]> OnPersonsSaving;
        Person[] CreatePersons(int num)
        {
            Person[] persons = new Person[num];
            Random rand = new Random();
            for (int i = 0; i < num; i++)
            {
                persons[i] = new Person()
                {
                    Birthdate = DateTime.Today.AddDays(-rand.Next(365 * 20, 365 * 50)),
                    RegTime = DateTime.Now.AddSeconds(-rand.Next(0, 86400 * 365)),
                    UserName = Guid.NewGuid().ToString(),
                    Mark = "My Mark:" + Guid.NewGuid().ToString(),
                };
            }
            return persons;
        }

        Stopwatch sw = new Stopwatch();
        public long SavePersons()
        {
            var persons = CreatePersons(10000);

            sw.Restart();
            OnPersonsSaving(persons);
            sw.Stop();
            return sw.ElapsedMilliseconds;
        }
    }
}